#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <sqlite3.h>
#include "list.h"
#include "command_parser.h"

#define PORT 10086
#define BUFFER_SIZE 1024

ListNode *head = NULL;

void *thread_function(void *arg);
void append(ListNode **head, int UserID, int Connect_fd);
void delete_node(ListNode **head, int UserID);
int parse_command(const char *input, char **command, char **param);

int main()
{
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    const char *message = "Welcome to the server";

    // 创建 socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置 SO_REUSEADDR 选项
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
    {
        perror("setsockopt failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 绑定 socket
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    if (bind(server_fd, (struct sockaddr *)&address, addrlen) < 0)
    {
        perror("bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0)
    {
        perror("listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("服务器启动，监听端口 %d\n", PORT);
    while (1)
    {
        // 接受连接
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
        {
            perror("accept failed");
            close(server_fd);
            exit(EXIT_FAILURE);
        }

        // 创建线程处理连接
        pthread_t thread1;
        int *id1 = (int *)malloc(sizeof(int));
        *id1 = new_socket;
        if (pthread_create(&thread1, NULL, thread_function, (void *)id1) != 0)
        {
            perror("创建线程1失败");
            exit(EXIT_FAILURE);
        }
    }

    // 发送欢迎消息
    send(new_socket, message, strlen(message), 0);
    printf("消息发送成功\n");

    // 关闭连接
    close(new_socket);
    close(server_fd);

    return 0;
}

void *thread_function(void *arg)
{
    int new_socket = *((int *)arg);
    int attempts = 0;               // 记录登陆次数
    const int MAX_ATTEMPTS = 3;     // 最大登录尝试次数
    char buffer[BUFFER_SIZE] = {0}; // 用于存储从客户端接收的数据和发送的数据。
    int UserID = 0;
    char username[127] = {0};
    char Password[127] = {0};
    char bb[127] = {0}; // 临时缓冲区，存储从客户端接收的数据。
    sqlite3 *db;
    sqlite3_stmt *stmt; // 声明 stmt 变量

    // 打开数据库
    if (sqlite3_open("users.db", &db))
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        close(new_socket);
        pthread_exit(NULL);
    }

    // 向客户端发送消息, 要求客户端输入用户名
    strcpy(buffer, "Please enter your username: ");
    send(new_socket, buffer, strlen(buffer), 0);
    read(new_socket, buffer, BUFFER_SIZE);
    strcpy(username, buffer);

    // 向客户端发送消息, 要求客户端输入密码
    strcpy(buffer, "Please enter your password: ");
    send(new_socket, buffer, strlen(buffer), 0);
    read(new_socket, buffer, BUFFER_SIZE);
    strcpy(Password, buffer);

    // 进行密码验证
    while (attempts < MAX_ATTEMPTS)
    {
      
        memset(buffer, 0, BUFFER_SIZE);
        if (recv(new_socket, buffer, sizeof(buffer), 0) > 0)
        {
            strcpy(Password, buffer);

            const char *sql = "SELECT id FROM users WHERE username = ? AND password = ? AND status = 0;";
            if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
            {
                fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
                close(new_socket);
                pthread_exit(NULL);
                
            }
            sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
            sqlite3_bind_text(stmt, 2, Password, -1, SQLITE_STATIC);

           //
           if (sqlite3_step(stmt) == SQLITE_DONE)
            {
                UserID = sqlite3_column_int(stmt, 0);
                snprintf(buffer, sizeof(buffer), "Login successful!!\n");
                send(new_socket, buffer, strlen(buffer), 0);

                // 更新用户状态为在线
                const char *update_sql = "UPDATE users SET status = 1 WHERE id = ?;";
                if (sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL) != SQLITE_OK)
                {
                    fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
                    close(new_socket);
                    pthread_exit(NULL);
                }
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                // 将用户ID和套接字描述符添加到在线用户表
                const char *insert_online_sql = "INSERT INTO online_users (user_id, connect_fd) VALUES (?, ?);";
                if (sqlite3_prepare_v2(db, insert_online_sql, -1, &stmt, NULL) != SQLITE_OK)
                {
                    fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
                    close(new_socket);
                    pthread_exit(NULL);
                }
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_bind_int(stmt, 2, new_socket);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                break;
            }
            else
            {
                snprintf(buffer, sizeof(buffer), "Login failed! Attempt %d of %d\n", attempts + 1, MAX_ATTEMPTS);
                send(new_socket, buffer, strlen(buffer), 0);
                attempts++;
            }

            sqlite3_finalize(stmt);
            printf("User %s failed to login\n", username);
        }
    }

    if (attempts == MAX_ATTEMPTS)
    {
        close(new_socket);
        pthread_exit(NULL);
    }

    // 登录成功后，将用户ID和套接字描述符添加到链表中
    append(&head, UserID, new_socket);

    char *command = NULL;
    char *param = NULL;
    ListNode *temp;
    int loop = 1;

    while (loop)
    // 循环读取用户输入的命令和参数
    {
        memset(buffer, 0, BUFFER_SIZE);
        read(new_socket, buffer, BUFFER_SIZE);
        printf("Received message: %s\n", buffer);

    command = NULL;
    param = NULL;
        if (parse_command(buffer, &command, &param) == 0)
        {
            printf("命令: %s\n", command);
            printf("参数: %s\n", param);
        }
        else
        {
            printf("解析命令失败\n");
        }
  
        if (strcmp(command, "cmd") == 0)
        {
            if (strcmp(param, "online_user") == 0)
            {
                memset(buffer, 0, sizeof(buffer));
                memset(bb, 0, sizeof(bb));
                temp = head;

                while (temp != NULL)
                {
                    sprintf(bb, "%d ", temp->UserID);
                    strcat(buffer, bb);
                    temp = temp->next;
                }
                strcat(buffer, "\n");
                send(new_socket, buffer, strlen(buffer), 0);
                printf("all user ID query succeeded!\n");
            }
        }

        if (strcmp(command, "all") == 0)
        {
            memset(buffer, 0, sizeof(buffer));
            memset(bb, 0, sizeof(bb));
            temp = head;
            sprintf(bb, "%d->", UserID);
            strcat(buffer, bb);
            strcat(buffer, param);

            while (temp != NULL)
            {
                send(temp->Connect_fd, buffer, strlen(buffer), 0);
                temp = temp->next;
            }
        }

        if (strcmp(command, "usr") == 0)
        {
            int sid = atoi(param);
            temp = head;
            int dia_socket = 0; // 声明并初始化 dia_socket
            while (temp != NULL)
            {
                if (temp->UserID == sid)
                {
                    int dia_socket = temp->Connect_fd;
                    int dia_loop = 1;
                    break;
                }
                temp = temp->next;
            }

            if (dia_socket == 0)
            {
                send(new_socket, "user not find!\n", strlen(buffer), 0);
            }
            int dia_loop = 1;
            while (dia_loop)
            {
                memset(buffer, 0, BUFFER_SIZE);
                read(new_socket, buffer, BUFFER_SIZE);
                if (strncmp(buffer, "quit", 4) == 0)
                {
                    memset(buffer, 0, BUFFER_SIZE);
                    strcat(buffer, "DIALOG OVER!");
                    send(new_socket, buffer, strlen(buffer), 0);
                    dia_loop = 0;
                }
                send(dia_socket, buffer, strlen(buffer), 0);
            }
        }

        if (strcmp(command, "private") == 0)
        {
            char *target_id_str = strtok(param, " ");
            char *message = strtok(NULL, "");
            if (target_id_str && message)
            {
                int target_id = atoi(target_id_str);
                temp = head;
                while (temp != NULL)
                {
                    if (temp->UserID == target_id)
                    {
                        send(temp->Connect_fd, message, strlen(message), 0);
                        break;
                    }
                    temp = temp->next;
                }
                if (temp == NULL)
                {
                    send(new_socket, "Target user not found!\n", strlen(buffer), 0);
                }
            }
            else
            {
                send(new_socket, "Invalid private message format!\n", strlen(buffer), 0);
            }
        }
        if (strcmp(command, "broadcast") == 0)
        
        {
            temp = head;
            while (temp != NULL)
            {
                if (temp->Connect_fd != new_socket)
                {
                    send(temp->Connect_fd, param, strlen(param), 0);
                }
                temp = temp->next;
            }
            printf("broadcast succeeded!\n");
        }

        if (strcmp(command, "exit") == 0)
        {
            delete_node(&head, UserID);

            const char *update_sql = "UPDATE users SET status = 0 WHERE id = ?;";
            if (sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL) != SQLITE_OK)
            {
                fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
                close(new_socket);
                pthread_exit(NULL);
            }
            sqlite3_bind_int(stmt, 1, UserID);
            sqlite3_step(stmt);
            sqlite3_finalize(stmt);

            const char *delete_online_sql = "DELETE FROM online_users WHERE user_id = ?;";
            if (sqlite3_prepare_v2(db, delete_online_sql, -1, &stmt, NULL) != SQLITE_OK)
            {
                fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
                close(new_socket);
                pthread_exit(NULL);
            }
            sqlite3_bind_int(stmt, 1, UserID);
            sqlite3_step(stmt);
            sqlite3_finalize(stmt);

            loop = 0;
        }

        // free(command);
        // free(param);
        if (loop == 0)
            break;
    }

    close(new_socket);
    sqlite3_close(db);
    pthread_exit(NULL);
}

// void append(ListNode **head, int UserID, int Connect_fd) {
//     ListNode *new_node = (ListNode *)malloc(sizeof(ListNode));
//     new_node->UserID = UserID;
//     new_node->Connect_fd = Connect_fd;
//     new_node->next = *head;
//     *head = new_node;
// }

// void delete_node(ListNode **head, int UserID) {
//     ListNode *current = *head;
//     ListNode *prev = NULL;

//     while (current != NULL) {
//         if (current->UserID == UserID) {
//             if (prev == NULL) {
//                 *head = current->next;
//             } else {
//                 prev->next = current->next;
//             }
//             free(current);
//             return;
//         }
//         prev = current;
//         current = current->next;
//     }
// }